package cc.abanlee.framework.web.core.handler;

import cc.abanlee.framework.apilog.core.service.ApiErrorLogFrameworkService;
import cc.abanlee.framework.apilog.core.vo.ApiErrorLog;
import cc.abanlee.framework.common.exception.ServiceException;
import cc.abanlee.framework.common.exception.enums.GlobalErrorCodeConstants;
import cc.abanlee.framework.common.pojo.CommonResult;
import cc.abanlee.framework.common.util.json.JsonUtils;
import cn.hutool.core.map.MapUtil;
import cn.hutool.extra.servlet.ServletUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * @author: create by 飞鱼
 * @version: v1.0
 * @description: 全局异常处理器
 * @date:2022/8/15
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    private ApiErrorLogFrameworkService apiErrorLogFrameworkService;

    public GlobalExceptionHandler() {
    }

    public GlobalExceptionHandler(ApiErrorLogFrameworkService apiErrorLogFrameworkService) {
        this.apiErrorLogFrameworkService = apiErrorLogFrameworkService;
    }

    //    public CommonResult<?> allExceptionHandler(HttpServletRequest request, Throwable ex) {
//
//        if(ex instanceof ServiceException){
//            return serviceExceptionHandler((ServiceException) ex);
//        }
//        return defaultExceptionHandler(request,ex);
//    }
    @ExceptionHandler(value = ServiceException.class)
    public  CommonResult<?> bizExceptionHandler(HttpServletRequest req, ServiceException ex) {
        log.error("发生业务异常！原因是：", ex);
        return CommonResult.error(ex.getCode(), ex.getMessage());
    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public  CommonResult<?> methodArgumentNotValidExceptionHandler(HttpServletRequest req, MethodArgumentNotValidException ex) {
        log.warn("[methodArgumentNotValidExceptionExceptionHandler]", ex);
        FieldError fieldError = ex.getBindingResult().getFieldError();
        return CommonResult.error(GlobalErrorCodeConstants.BAD_REQUEST.getCode(), String.format("请求参数不正确:%s",fieldError.getDefaultMessage()));
    }

    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public  CommonResult<?> missingServletRequestParameterExceptionHandler(HttpServletRequest req, MissingServletRequestParameterException ex) {
        log.warn("[missingServletRequestParameterExceptionHandler]", ex);
        return CommonResult.error(GlobalErrorCodeConstants.BAD_REQUEST.getCode(), String.format("请求参数缺失:%s",ex.getParameterName()));
    }

    @ExceptionHandler(value = AccessDeniedException.class)
    public  CommonResult<?> accessDeniedExceptionHandler(HttpServletRequest req, AccessDeniedException ex) {
        log.warn("[accessDeniedException]", ex);
        return CommonResult.error(GlobalErrorCodeConstants.FORBIDDEN.getCode(), String.format("拒绝访问:%s",ex.getMessage()));
    }




//    /**
//     * 处理业务异常 ServiceException
//     *
//     * 例如说，商品库存不足，用户手机号已存在。
//     */
//    @ExceptionHandler(value = ServiceException.class)
//    public CommonResult<?> serviceExceptionHandler(ServiceException ex) {
//        log.info("[serviceExceptionHandler]", ex);
//        return CommonResult.error(ex.getCode(), ex.getMessage());
//    }

    /**
     * 处理系统异常，兜底处理所有的一切
     */
    @ExceptionHandler(value = Exception.class)
    public CommonResult<?> defaultExceptionHandler(HttpServletRequest req, Throwable ex) {
        log.error("[defaultExceptionHandler]", ex);
        // 插入异常日志
        this.createExceptionLog(req, ex);
        // 返回 ERROR CommonResult
        return CommonResult.error(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getMsg());
    }

    private void createExceptionLog(HttpServletRequest req, Throwable e) {
        // 插入错误日志
        ApiErrorLog errorLog = new ApiErrorLog();
        try {
            // 初始化 errorLog
            initExceptionLog(errorLog, req, e);
            // 执行插入 errorLog
           // apiErrorLogFrameworkService.createApiErrorLog(errorLog);
        } catch (Throwable th) {
            log.error("[createExceptionLog][url({}) log({}) 发生异常]", req.getRequestURI(),  JsonUtils.toJsonString(errorLog), th);
        }
    }

    private void initExceptionLog(ApiErrorLog errorLog, HttpServletRequest request, Throwable e){
        errorLog.setRequestUrl(request.getRequestURI());
        Map<String, Object> requestParams = MapUtil.<String, Object>builder()
                .put("query", ServletUtil.getParamMap(request))
                .put("body", ServletUtil.getBody(request)).build();
    }
}
